<script lang="tsx">
import {
  ElTable,
  ElTableColumn,
  ComponentSize
} from 'element-plus'
import { myProps } from './types/myprops';
import { defineComponent, ref, computed, unref, watch, onMounted, reactive,withModifiers,getCurrentInstance } from 'vue'
import type { TableProps, TableColumn, Pagination, TableSetProps } from './types'
import { set, get } from 'lodash-es'
import { getSlot } from '@/utils/tsxHelper'
import TableActions from './components/TableActions.vue'
import ColumnContent from './components/ColumnContent.vue'
import EPagination from './components/EPagination.vue'
import HeaderFilter from './components/HeaderFilter.vue'
import RightClickMenu from "./components/RightClickMenu.vue"
import {IdxTableColumn, SelTableConlumn, renderPreview, getColumn, actionPush} from './components/CustomElement.tsx'
import {TableData} from "@/api/table/types";
import { summaryHelper } from './helper/summaryHelper.ts'
export default defineComponent({
  name: 'Table',
  props: myProps,
  emits: ['update:pageSize', 'update:currentPage', 'register', 'headerFilterSumit','sortChange'],
  setup(props, { attrs, emit, slots, expose }) {
      const {proxy} = getCurrentInstance()
      const elTableRef = ref<ComponentRef<typeof ElTable>>()
      const columnsJson = {};
      props.columns.forEach(object => {
          columnsJson[object.field] = object
      });

    // 注册
    onMounted(() => {
      const tableRef = unref(elTableRef)
      emit('register', tableRef?.$parent, elTableRef)
    })
    const multipleSelectionRef = ref(props.multipleSelection)
    const pageSizeRef = ref(props.pageSize)
    const currentPageRef = ref(props.currentPage)
    // useTable传入的props
    const outsideProps = ref<TableProps>({})

    const mergeProps = ref<TableProps>({})

    const getProps = computed(() => {
      const propsObj = { ...props }; Object.assign(propsObj, unref(mergeProps))
      return propsObj
    })
    const setProps = (props: TableProps = {}) => { mergeProps.value = Object.assign(unref(mergeProps), props); outsideProps.value = { ...props } as any; }

    const setColumn = (columnProps: TableSetProps[], columnsChildren?: TableColumn[]) => {
      const { columns } = unref(getProps)
      for (const v of columnsChildren || columns) {
        for (const item of columnProps) {
          if (v.field === item.field) {
            set(v, item.path, item.value)
          } else if (v.children?.length) {
            setColumn(columnProps, v.children)
          }
        }
      }
    }

    const delColumn = (field: string) => {
      const { columns } = unref(getProps)
      const index = columns.findIndex((item) => item.field === field)
      if (index > -1) {
        columns.splice(index, 1)
      }
    }

      const getSummaries = (param: SummaryMethodProps) => {
          const { columns, data } = param
          const sums: (string | VNode)[] = []
          columns.forEach((column, index) => {
              if (index === 0) {
                  sums[index] = h('div', { style: { textDecoration: 'underline' } }, [
                      'Total Cost',
                  ])
                  return
              }
              const values = data.map((item) => Number(item[column.property]))
              if (!values.every((value) => Number.isNaN(value))) {
                  sums[index] = `$ ${values.reduce((prev, curr) => {
                      const value = Number(curr)
                      if (!Number.isNaN(value)) {
                          return prev + curr
                      } else {
                          return prev
                      }
                  }, 0)}`
              } else {
                  sums[index] = 'N/A'
              }
          })

          return sums
      }


      const getSummaries2 = (param) => {
        const sums = summaryHelper(param, columnsJson, props.summaryname)
          return sums
      }

    // const refresh = () => { emit('refresh')  }
    const changSize = (size: ComponentSize) => { setProps({ size }) }
    const confirmSetColumn = (columns: TableColumn[]) => {  setProps({ columns })  }
    expose({ setProps, setColumn, delColumn, elTableRef })

    // const pagination = computed(() => {return Object.assign({},unref(getProps).pagination) })

    const actionClick = (type, parm) => {  actionPush(type, parm);  }

    // watch( () => unref(getProps).multipleSelection, (val: number) => {  console.log(multipleSelectionRef.value)  })
    watch( () => unref(getProps).pageSize, (val: number) => {  pageSizeRef.value = val  })
    watch(() => unref(getProps).currentPage,(val: number) => { currentPageRef.value = val  })
    watch(() => pageSizeRef.value,(val: number) => {  emit('update:pageSize', val)  })
    watch( () => currentPageRef.value, (val: number) => { emit('update:currentPage', val)  })
    const handleRowClick = (row: any, column: any, event: e) => {
        const selectionRows = elTableRef?.value.getSelectionRows();
       if(unref(selectionRows).indexOf(row) != -1){
           elTableRef.value.toggleRowSelection(row, false)
       }else{
            elTableRef.value.toggleRowSelection(row, true)
       }
    }
    const getRowClassName = ({ row, rowIndex }) => {
        const selectionRows = elTableRef?.value.getSelectionRows();
        if (unref(selectionRows).indexOf(row) != -1) {
              return 'selected';
        }
        return '';
      };
    const headerFilterSumit = (data: any) => {emit('headerFilterSumit', data)}
      // 菜单
      // const menus = ref([]);
    const onContextmenu = (row: any, column: any, cell: HTMLTableCellElement, event: Event) =>{
        // 打开右键菜单
        proxy.$refs["rightClickMenu"].open(row, column, event);
    }
    const handleSortChange = ({ column, prop, order }) =>{emit('sortChange', prop, order)}
    const getBindValue = computed(() => {
      const bindValue: Recordable = { ...attrs, ...unref(getProps) }
      delete bindValue.columns;  delete bindValue.data;delete bindValue.align;
      return bindValue
    })

    const renderTableColumn = (columnsChildren?: TableColumn[]) => {
      const { columns, align, headerAlign, showOverflowTooltip, imagePreview, videoPreview } = unref(getProps)
      return (columnsChildren || columns).map((v) => {
        if (v.hidden) return null
          const props = { ...v } as any
          if(props['globalsort']) props['sortable'] = 'custom'
          if (props.children) delete props.children
          const children = v.children
          const slots = {
            default: (...args: any[]) => {
              const data = args[0]
              let isPreview = imagePreview.some((item) => (item as string) === v.field) || videoPreview.some((item) => (item as string) === v.field)
              return children && children.length
                ? renderTableColumn(children)
                : props?.slots?.default
                    ? props.slots.default(...args)
                    : v?.formatter
                        ? v?.formatter?.(data.row, data.column, get(data.row, v.field), data.$index)
                        : isPreview
                            ? renderPreview(get(data.row, v.field), v.field, imagePreview, videoPreview)
                            : getColumn(data.row, v)
            }
          }
          if (props?.slots?.header) {
            slots['header'] = (...args: any[]) => props.slots.header(...args)
          }else{
              if(v.filter){
                  slots['header'] = (...args: any[]) => {
                      return (<HeaderFilter  field={v.field} type={v.filter} title={v.label} onHeaderFilterSumit={headerFilterSumit}/>)
                  }
              }
          }
          return (
                <ElTableColumn
                  showOverflowTooltip={showOverflowTooltip}
                  align={align}
                  headerAlign={headerAlign}
                  {...props}
                  prop={v.field} >{slots}</ElTableColumn>
          )
      })
    }

    return () => {
      const tableSlots = {}
      if (getSlot(slots, 'empty')) {
        tableSlots['empty'] = (...args: any[]) => getSlot(slots, 'empty', args)
      }
      if (getSlot(slots, 'append')) {
        tableSlots['append'] = (...args: any[]) => getSlot(slots, 'append', args)
      }
        // 自定义头部的函数
      const renderHeader = () => (  <TableActions  columns={unref(getProps).columns}  onChangSize={changSize} onConfirm={confirmSetColumn}  /> );

      const headercolumnsetting = ()=> ( <ElTableColumn class-name="columnsetting" fixed="right" align="right" width="20px" renderHeader={renderHeader} />)
      return (
            <div v-loading={unref(getProps).loading}>
                {<EPagination  v-model:pageSize={pageSizeRef.value} v-model:currentPage={currentPageRef.value} pagination={unref(getProps).pagination} /> }
              {unref(getProps).customContent ? (
                <ColumnContent  data={unref(getProps).data} class={unref(getProps).cardWrapClass} style={unref(getProps).cardWrapStyle}  bodyClass={unref(getProps).cardBodyClass}  bodyStyle={unref(getProps).cardBodyStyle} />
              ) : (
                  <ElTable
                      onCellContextmenu={onContextmenu}
                      ref={elTableRef}
                      data={unref(getProps).data} {...unref(getBindValue)}
                      onSortChange={handleSortChange}
                      onRowClick={handleRowClick}
                     rowClassName={getRowClassName}
                      summaryMethod={getSummaries2}
                  >
                    {SelTableConlumn()}  {IdxTableColumn()} {renderTableColumn()} {headercolumnsetting()} {{...tableSlots}}
                  </ElTable>
              )}
                <RightClickMenu ref="rightClickMenu" />
            </div>
      )
    }
  }
})
</script>
<style lang="less">

  .el-table.is-scrolling-left.el-table--border .el-table-fixed-column--left.is-last-column.el-table__cell {
       border-right: 1px solid transparent;
  }
  .el-table--border .el-table__cell {
       /*border-right: 1px solid rgb(0 0 0 / 0%)*/
      border-left: none;
      border-right: none;
  }

  .el-table {
      /*--el-table-border-color: rgb(0 0 0 / 0%);*/
      --el-table-header-bg-color: #f4f4f4;
      /*--el-table-border: 1px solid rgb(0 0 0 / 0%);*/
      .el-table__row{
          &.selected{
              background-color: #f9f8ebe3 !important;
          }
          &.el-table__row--striped{
              &.selected td{
                  background-color: #f9f8ebe3 !important;
              }
          }
      }

      td.el-table__cell{
        border-bottom: 1px solid #e7e9eb;
        .cell  {
          white-space: nowrap;
        }
      }
      th.el-table__cell.is-leaf {
        border-bottom: 1px solid #e7e9eb;
        border-top: 1px solid #e7e9eb;
      }
  }

  .table-col-link{
    color: var(--el-color-primary);
    &:hover{
      color: #4069FF;
      cursor: pointer;
    }
  }

  .el-table-column--selection .cell{
      margin-left:-7px !important;
  }
  .columnsetting::before{
      box-shadow: none !important;
  }

  .el-table__body .columnsetting{
      width: 0px !important;
  }

  .el-table__header .columnsetting .cell{
      padding: 0px !important;
  }


.el-table--default {
    font-size: 12px;
    th.el-table__cell:hover{
      border-left: 1px solid #e7e9eb;
      border-right: 1px solid #e7e9eb;
    }
    .el-table__cell {
      padding: 8px 0;
      border-right: 1px solid transparent;
      border-left: 1px solid transparent;
    }
}

.el-table--border .el-table__inner-wrapper::after, .el-table--border::after, .el-table--border::before, .el-table__inner-wrapper::before {
    /*content: "";*/
    /*position: absolute;*/
    background-color: transparent;
    /*z-index: calc(var(--el-table-index) + 2);*/
}
.el-table__border-left-patch{
    width: 0px;
}
:root{
    --el-text-color-regular: #022433;
    --el-text-color-secondary: #022433;
}

</style>
<style scoped>

</style>
